/**
* \file	ASTChecker.cpp
* \author Caio Arce Nishibe (caionishibe@gmail.com)
* \date	August, 2014
* \brief AST Checker Implementation.
*/
#include "ASTChecker.h"


ASTChecker::ASTChecker(SymbolTable *symbTab)
{
	this->symbTab = symbTab;
}

ASTChecker::~ASTChecker()
{
	this->symbTab = NULL;
}

void ASTChecker::VisitProgram(ASTNode *node)
{
	//cout << "Checking program" << endl;
	ASTNode *child;
	for (child = node->children; child != NULL; child = child->sibling)
	{

		child->Accept(this);
	}
}

void ASTChecker::VisitName(ASTNode *node)
{
	//cout << "Checking name" << endl;

	bool name = true;
	ASTNode * child;
	for (child = node->children; child != NULL; child = child->sibling)
	{
		if (name)
		{
			name = false;
		}

		child->Accept(this);
	}


}

void ASTChecker::VisitVariable(ASTNode *node)
{
	//cout << "Cheking variable" << endl;

	ASTNode * varName = node->children;
	ASTNode * varVal = varName->sibling;

	string strVarName;
	varName->value.GetValue(STRING, &strVarName);

	string strOwner;

	ASTNode *parent = node->parent;
	if (parent != NULL && parent->kind == PROGRAM || parent->kind == MESSAGE)
	{
		//navigate tree searching for program name
		ASTNode *name = parent->children;
		if (name->kind == NAME)
		{
			ASTNode *identifier = name->children;
			identifier->value.GetValue(STRING, &strOwner);
		}
	}
	

	Symbol *symb = new Symbol(strVarName, DOUBLE, varVal->value, strOwner, varName->lineNumber);
	this->symbTab->InsertSymbol(symb);
}

void ASTChecker::VisitRules(ASTNode *node)
{
	//cout << "Checking rules" << endl;

	ASTNode * child;
	for (child = node->children; child != NULL; child = child->sibling)
	{
		child->Accept(this);
	}
}
void ASTChecker::VisitRulesSet(ASTNode *node)
{
	//cout << "Checking rule set" << endl;

	ASTNode * child;
	for (child = node->children; child != NULL; child = child->sibling)
	{
		child->Accept(this);
	}
}
void ASTChecker::VisitRule(ASTNode *node)
{
	//cout << "Checking rule" << endl;

	ASTNode * child;
	for (child = node->children; child != NULL; child = child->sibling)
	{
		child->Accept(this);
	}
}
void ASTChecker::VisitCondition(ASTNode *node)
{
	//cout << "Checking condition" << endl;

	ASTNode * child;
	child = node->children;

	if (child->kind == LOGIC_OP)
	{
		LogicOp op;
		child->value.GetValue(LOGIC, &op);

		if (op != NOT)
		{
			string opVal;
			switch (op)
			{
			case NOT:
				opVal = "NOT";
				break;
			case AND:
				opVal = "AND";
				break;
			case OR:
				opVal = "OR";
				break;
			}

			cerr << "Error: Expecting NOT, found " << opVal << " on line " << child->lineNumber << endl;
			exit(1);
		}
	}


	for (child = node->children; child != NULL; child = child->sibling)
	{
		child->Accept(this);
	}
}
void ASTChecker::VisitLogicOperator(ASTNode *node)
{
	//cout << "Checking logic operator" << endl;
}
void ASTChecker::VisitInternalCondition(ASTNode *node)
{
	//cout << "Checking internal condition" << endl;


	ASTNode *child;

	for (child = node->children; child != NULL; child = child->sibling)
	{
		child->Accept(this);
	}
}
void ASTChecker::VisitComparationOperator(ASTNode *node)
{
	//cout << "Checking comparation operator" << endl;
}
void ASTChecker::VisitArithmeticOperator(ASTNode *node)
{
	//cout << "Checking arithmetic operator" << endl;
}
void ASTChecker::VisitArithmeticExpression(ASTNode *node)
{
	//cout << "Checking arithmetic expression" << endl;
	ASTNode * child;
	for (child = node->children; child != NULL; child = child->sibling)
	{
		child->Accept(this);
	}
}
void ASTChecker::VisitAction(ASTNode * node)
{
	//cout << "Checking action" << endl;
	ASTNode * child;
	for (child = node->children; child != NULL; child = child->sibling)
	{
		child->Accept(this);
	}
}
void ASTChecker::VisitCommand(ASTNode * node)
{
	//cout << "Checking command" << endl;
	ASTNode * child;
	for (child = node->children; child != NULL; child = child->sibling)
	{
		child->Accept(this);
	}
}
void ASTChecker::VisitCmd(ASTNode *node)
{
	//cout << "Checking cmd" << endl;
	ASTNode * child;
	for (child = node->children; child != NULL; child = child->sibling)
	{
		child->Accept(this);
	}
}
void ASTChecker::VisitAssignment(ASTNode *node)
{
	//cout << "Checking assignment" << endl;
	ASTNode * child;
	for (child = node->children; child != NULL; child = child->sibling)
	{
		child->Accept(this);
	}
}
void ASTChecker::VisitReadSensor(ASTNode *node)
{
	//cout << "Checking read sensor" << endl;
	ASTNode * child;
	for (child = node->children; child != NULL; child = child->sibling)
	{
		child->Accept(this);
	}
}
void ASTChecker::VisitWriteActuator(ASTNode *node)
{
	//cout << "Checking write actuator" << endl;
	ASTNode * child;
	for (child = node->children; child != NULL; child = child->sibling)
	{
		child->Accept(this);
	}
}
void ASTChecker::VisitIdentifier(ASTNode *node)
{
	//cout << "Checking identifier" << endl;
}
void ASTChecker::VisitNumber(ASTNode *node)
{
	//cout << "Checking number" << endl;
}
void ASTChecker::VisitMessage(ASTNode *node)
{
	//cout << "Checking message" << endl;
	ASTNode * child;
	for (child = node->children; child != NULL; child = child->sibling)
	{
		child->Accept(this);
	}
}
